import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage, SystemMessage, BaseMessage, ToolMessage } from "@langchain/core/messages";
import { getDatabase } from "../database/init";
import { concat } from "@langchain/core/utils/stream";
import { AIToolsRegistry } from "./aiToolsRegistry";

// 聊天模型配置
export class LangChainService {
  private chatModel: ChatOpenAI;
  private db: any;
  private currentUserId?: string;
  private toolsRegistry: AIToolsRegistry;

  constructor() {
    this.db = getDatabase();
    this.toolsRegistry = new AIToolsRegistry(this.db, this.currentUserId);
    
    // 初始化聊天模型
    this.chatModel = new ChatOpenAI({
      openAIApiKey: process.env.OPENAI_API_KEY,
      configuration: {
        baseURL: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'
      },
      model: "gpt-4o",
      temperature: 0.7,
      streaming: true
    });
  }

  // 流式聊天
  async *streamChat(messages: any[], userId?: string, abortSignal?: AbortSignal): AsyncGenerator<any, void, unknown> {
    try {
      console.log('[LangChain] 🚀 开始流式聊天');
      console.log('[LangChain] 📥 输入消息:', JSON.stringify(messages, null, 2));
      console.log('[LangChain] 👤 用户ID:', userId);
      
      // 设置当前用户ID，供工具使用
      this.currentUserId = userId;
      this.toolsRegistry = new AIToolsRegistry(this.db, this.currentUserId);
      
      const langchainMessages = this.convertMessages(messages);
      console.log('[LangChain] 🔄 转换后的消息:', JSON.stringify(langchainMessages, null, 2));
      
      // 定义工具
      const tools: any[] = this.toolsRegistry.getAllTools();
      
      console.log('[LangChain] 🔗 开始调用模型流式接口...');
      
      // 使用LangChain的流式工具调用机制
      const modelWithTools = this.chatModel.bindTools(tools);
      const stream = await modelWithTools.stream(langchainMessages);
      
      console.log('[LangChain] ✅ 模型流式接口调用成功');
      
      let accumulatedContent = '';
      let accumulatedChunk: any = null;
      
      console.log('[LangChain] 📡 开始处理流式数据...');
      for await (const chunk of stream) {
        // 检查是否被中断
        if (abortSignal?.aborted) {
          console.log('[LangChain] ⚠️ 流式聊天被中断');
          break;
        }
        
        console.log(`[LangChain] 📦 收到chunk:`, JSON.stringify(chunk, null, 2));
        
        // 累积消息块以构建完整的工具调用
        if (accumulatedChunk === null) {
          accumulatedChunk = chunk;
        } else {
          accumulatedChunk = concat(accumulatedChunk, chunk);
        }
        
        // 处理内容流
        if (chunk.content) {
          accumulatedContent += chunk.content;
          yield {
            type: 'content',
            content: chunk.content,
            messageId: Date.now().toString()
          };
        }
        
        // 处理工具调用 - 只在工具名称完整时发送
        if (chunk.tool_call_chunks && chunk.tool_call_chunks.length > 0) {
          console.log('[LangChain] 🔧 检测到工具调用chunks:', chunk.tool_call_chunks);
          const toolName = chunk.tool_call_chunks[0].name;
          console.log('[LangChain] 🔍 工具名称:', toolName);
          console.log('[LangChain] 🔍 工具名称类型:', typeof toolName);
          
          // 只在工具名称完整时才发送工具调用信息
          if (toolName && toolName !== '') {
            const chineseName = this.toolsRegistry.getToolChineseName(toolName);
            console.log('[LangChain] 🔍 中文名称:', chineseName);
            yield {
              type: 'tool_call',
              toolCall: {
                name: toolName,
                chineseName: chineseName,
                args: chunk.tool_call_chunks[0].args
              },
              messageId: Date.now().toString()
            };
          }
        }
      }
      
      // 检查是否有完整的工具调用需要执行
      if (accumulatedChunk && accumulatedChunk.tool_calls && accumulatedChunk.tool_calls.length > 0) {
        console.log('[LangChain] 🔧 检测到完整工具调用:', accumulatedChunk.tool_calls);
        
        const toolMessages: ToolMessage[] = [];
        
        for (const toolCall of accumulatedChunk.tool_calls) {
          // 检查是否被中断
          if (abortSignal?.aborted) {
            console.log('[LangChain] ⚠️ 工具执行被中断');
            break;
          }
          
          console.log(`[LangChain] 🔧 执行工具: ${toolCall.name}`);
          console.log(`[LangChain] 📥 工具参数:`, toolCall.args);
          
          // 发送工具调用信息（确保用户看到正在执行什么）
          const chineseName = this.toolsRegistry.getToolChineseName(toolCall.name);
          yield {
            type: 'tool_call',
            toolCall: {
              name: toolCall.name,
              chineseName: chineseName,
              args: toolCall.args
            },
            messageId: Date.now().toString()
          };
          
          try {
            // 查找对应的工具
            const tool = tools.find(t => t.name === toolCall.name);
            if (!tool) {
              throw new Error(`工具 ${toolCall.name} 未找到`);
            }
            
            // 执行工具
            const result = await tool.invoke(toolCall.args);
            console.log(`[LangChain] ✅ 工具执行结果:`, result);
            
            // 创建工具消息
            const toolCallId = toolCall.id || `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
            const toolMessage = new ToolMessage({
              content: result,
              tool_call_id: toolCallId
            });
            toolMessages.push(toolMessage);
            
            // 发送工具执行结果
            const chineseName = this.toolsRegistry.getToolChineseName(toolCall.name);
            yield {
              type: 'tool_result',
              toolResult: {
                name: toolCall.name,
                chineseName: chineseName,
                result: result
              },
              messageId: Date.now().toString()
            };
            
          } catch (error) {
            console.error(`[LangChain] ❌ 工具执行失败:`, error);
            
            // 发送工具执行错误
            const chineseName = this.toolsRegistry.getToolChineseName(toolCall.name);
            yield {
              type: 'tool_error',
              toolError: {
                name: toolCall.name,
                chineseName: chineseName,
                error: error instanceof Error ? error.message : '工具执行失败'
              },
              messageId: Date.now().toString()
            };
          }
        }
        
        // 如果有工具执行结果，将结果发送回模型获取最终响应
        if (toolMessages.length > 0) {
          console.log('[LangChain] 🔄 将工具结果发送回模型...');
          
          // 构建包含工具结果的消息历史
          const messagesWithToolResults = [
            ...langchainMessages.slice(0, -1), // 除了最后一条AI消息外的所有消息
            accumulatedChunk, // AI消息（包含tool_calls）
            ...toolMessages // 工具结果消息
          ];
          
          console.log('[LangChain] 📤 发送给模型的消息历史:', JSON.stringify(messagesWithToolResults, null, 2));
          
          // 再次调用模型获取最终响应
          const finalStream = await modelWithTools.stream(messagesWithToolResults);
          
          for await (const finalChunk of finalStream) {
            // 检查是否被中断
            if (abortSignal?.aborted) {
              console.log('[LangChain] ⚠️ 最终响应被中断');
              break;
            }
            
            if (finalChunk.content) {
              yield {
                type: 'content',
                content: finalChunk.content,
                messageId: Date.now().toString()
              };
            }
          }
        }
      }
      
      console.log('[LangChain] ✅ 流式聊天完成');
      
    } catch (error) {
      console.error('[LangChain] ❌ 流式聊天错误:', error);
      yield {
        type: 'error',
        error: error instanceof Error ? error.message : '聊天发生错误',
        messageId: Date.now().toString()
      };
    }
  }

  // 非流式聊天
  async chat(messages: any[], userId?: string): Promise<any> {
    try {
      console.log('[LangChain] 🚀 开始聊天');
      console.log('[LangChain] 📥 输入消息:', JSON.stringify(messages, null, 2));
      console.log('[LangChain] 👤 用户ID:', userId);
      
      this.currentUserId = userId;
      this.toolsRegistry = new AIToolsRegistry(this.db, this.currentUserId);
      
      const langchainMessages = this.convertMessages(messages);
      
      // 定义工具
      const tools = this.toolsRegistry.getAllTools();
      
      const response = await this.chatModel.bindTools(tools).invoke(langchainMessages);
      
      console.log('[LangChain] ✅ 聊天完成');
      return {
        content: response.content,
        toolCalls: response.tool_calls || []
      };
    } catch (error) {
      console.error('[LangChain] ❌ 聊天错误:', error);
      throw error;
    }
  }

  // 转换消息格式
  private convertMessages(messages: any[]): BaseMessage[] {
    return messages.map(msg => {
      switch (msg.role) {
        case 'user':
          return new HumanMessage(msg.content);
        case 'assistant':
          return new AIMessage(msg.content);
        case 'system':
          return new SystemMessage(msg.content);
        default:
          return new HumanMessage(msg.content);
      }
    });
  }
}